package org.example.sort;

import java.io.*;
import java.util.LinkedList;

/**
 * 归并排序文件，直接对文件进行归并
 */
public class SortByMerges {
    /**
     * @param files  需要排序的文件的根目录，因为我是放在nums的，所以我的根目录是"./nums"
     */
    int cc = 0;

    public void sortByMerges(String file, String bigFileName) throws IOException {
        File Filelist = new File(file);
        File[] files = Filelist.listFiles();
        /**
         * 在小文件内归并排序
         */
         for(int i=0;i<files.length;i++){
             sortByMerges(files[i]);
         }
        /**
         *接下来将文件中的数据开始合并，因为我是从大到小进行排列，所以接下来，就是将这些文件写入到大文件中去
         */
        filesMerge(files, bigFileName);
        System.out.println(cc);

    }

    /**
     * 归并排序
     *
     * @param files 待排序的小文件
     * @throws IOException
     */
    public void sortByMerges(File files) throws IOException {
        int count = 0;
        FileReader fileReader = new FileReader(files);
        try {
            while (fileReader.read() != -1) {
                count++;
            }
        } finally {
            fileReader.close();
        }
        //将数据放入数组
        int[] nums = new int[count];
        int start = 0;
        fileReader = new FileReader(files);
        try {
            int num;
            while ((num = fileReader.read()) != -1) {
                nums[start++] = num;
            }
        } finally {
            fileReader.close();
        }
        sortByMerges(0, nums.length - 1, nums);
        FileWriter fileWriter = new FileWriter(files);
        try {
            for (int i = 0; i < nums.length; i++) {

                fileWriter.write(nums[i]);
            }
        } finally {
            fileWriter.close();
        }
    }

    /**
     * 利用递归进行归并排序
     *
     * @param start
     * @param end
     * @param nums
     */
    public void sortByMerges(int start, int end, int[] nums) {
        if (start >= end) return;
        int mid = start + (end - start) / 2;
        sortByMerges(start, mid, nums);
        sortByMerges(mid + 1, end, nums);
        merges(start, mid, end, nums);
    }

    private void merges(int start, int mid, int end, int[] nums) {
        int[] temp = new int[end - start + 1];
        int x = start, y = mid + 1;
        int init = 0;
        while (x <= mid && y <= end) {
            if (nums[x] > nums[y]) {
                temp[init++] = nums[x++];
            } else if (nums[x] < nums[y]) {
                temp[init++] = nums[y++];
            } else {
                temp[init++] = nums[x++];
                temp[init++] = nums[y++];
            }
        }
        /**
         * 将剩余的数自放入数组
         */
        while (x <= mid) {
            temp[init++] = nums[x++];
        }
        while (y <= end) {
            temp[init++] = nums[y++];
        }
        /**
         * 归并后，将数据合并到数组里去
         */
        for (int i = 0; i < temp.length; i++) {
            nums[start + i] = temp[i];
        }
    }

    /**
     * 将多个排序后的小文件合并到大文件
     *
     * @param files       小文件的数组
     * @param bigFileName 排序后的文件名称
     */
    public void filesMerge(File[] files, String bigFileName) throws IOException {
        LinkedList<BufferedReader> bufferedReaderLinkedList = new LinkedList<>();
        FileWriter fileWriter = new FileWriter(new File(bigFileName));
        /**
         * 校验数据总数
         */
        int numCount = 0;
        try {
            /**
             * 初始化io读取
             */
            for (int i = 0; i < files.length; i++) {
                bufferedReaderLinkedList.add(new BufferedReader(new FileReader(files[i])));
            }
            /**
             * 开始归并读取
             */
            while (bufferedReaderLinkedList.size() > 0) {
                int maxPositon = 0, max = -1;
                for (int i = 0; i < bufferedReaderLinkedList.size(); i++) {
                    bufferedReaderLinkedList.get(i).mark(1);
                    int temp = bufferedReaderLinkedList.get(i).read();
                    bufferedReaderLinkedList.get(i).reset();
                    if (temp != -1) {
                        if (max < temp) {
                            max = temp;
                            maxPositon = i;
                        }
                    }
                }
                if (max != -1) {
                    fileWriter.write(max);
                    bufferedReaderLinkedList.get(maxPositon).read();
                    numCount++;
                } else {
                    bufferedReaderLinkedList.get(maxPositon).close();
                    bufferedReaderLinkedList.remove(maxPositon);
                }
            }
        } finally {
            fileWriter.close();
        }
        System.out.println("最终排序的数字总和为:" + numCount);
    }

    public static void main(String[] args) throws IOException {
        SortByMerges sortByMerges = new SortByMerges();
        sortByMerges.sortByMerges("./nums", "sortNum.txt");
    }

}
